package com.yeziji.devops.config.aspect;

import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.datasource.FlexDataSource;
import com.yeziji.common.context.OnlineContext;
import com.yeziji.devops.utils.ParseUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.Optional;

/**
 * @author hwy
 * @since 2024/10/10 16:57
 **/
@Slf4j
@Aspect
@Component
public class TransactionAspect {
    @Around("@within(transactional) || @annotation(transactional)")
    public Object transactionalChooseDataSourceHandler(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
        transactional = ParseUtils.getAnnotation(pjp, Transactional.class);
        if (transactional == null) {
            return pjp.proceed();
        }

        // 非事物模式下数据源为默认数据源
        FlexDataSource dataSource = FlexGlobalConfig.getDefaultConfig().getDataSource();
        if (dataSource != null && Objects.equals(Propagation.NOT_SUPPORTED, transactional.propagation())) {
            String curSourceKey = DataSourceKey.get();
            String defaultSourceKey = Optional.ofNullable(OnlineContext.getDataSourceKey()).orElse(dataSource.getDefaultDataSourceKey());
            // 切换为初始指定的数据源
            // 如果与指定的不相同，说明可能做过切库查询操作(通常都是通过 DevopsService 切库)
            if (!Objects.equals(curSourceKey, defaultSourceKey)) {
                DataSourceKey.use(defaultSourceKey);
                Object proceed = pjp.proceed();
                // 执行完毕后切换为原来的数据源, 不做清除操作交给 DevopsService 清除
                DataSourceKey.use(curSourceKey);
                return proceed;
            }
        }
        return pjp.proceed();
    }
}
